package br.com.controlador;

import br.com.modelo.Fornecedor;
import br.com.modelo.NfeEntradaCabecalho;
import br.com.modelo.NfeEntradaDetalhe;
import br.com.modelo.Produto;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import org.primefaces.event.SelectEvent;
import util.Biblioteca;
import util.JPAUtil;
import util.JSFUtil;

/**
 *
 * @author Gilberto 04/07/2012
 */
@ManagedBean
@SessionScoped
public class NfeEntradaControler implements Serializable {

    private NfeEntradaCabecalho nfe_entrada_cabecalho;
    private NfeEntradaDetalhe nfe_entrada_detalhe;
    private List<NfeEntradaDetalhe> Listnfe_entrada_detalheEdicao;
    private List<Produto> listProduto;
    private List<Fornecedor> listFornecedores;
    private Produto produto;
    private String txt1;
    private String txt2;
    //edicao
//    @ManagedProperty(value = "#{param.idEdicao}")
    public static Integer idEdicao = null;

    @PostConstruct
    public void init() {
        setNfe_entrada_cabecalho(new NfeEntradaCabecalho());
        setProduto(new Produto());
        nfe_entrada_detalhe = new NfeEntradaDetalhe();
//        verificaEdicao();
    }

    /**
     * @return the nfe_entrada_cabecalho
     */
    public NfeEntradaCabecalho getNfe_entrada_cabecalho() {
        return nfe_entrada_cabecalho;
    }

    /**
     * @param nfe_entrada_cabecalho the nfe_entrada_cabecalho to set
     */
    public void setNfe_entrada_cabecalho(NfeEntradaCabecalho nfe_entrada_cabecalho) {
        this.nfe_entrada_cabecalho = nfe_entrada_cabecalho;
    }

    /**
     * @return the txt1
     */
    public String getTxt1() {
        return txt1;
    }

    /**
     * @param txt1 the txt1 to set
     */
    public void setTxt1(String txt1) {
        this.txt1 = txt1;
    }

    public List<String> complete(String query) {
        setListProduto(Produto.retornaProdutos());
        List<String> r = new ArrayList<String>();
        for (Produto v : getListProduto()) {
            if (v.getDescricao().toUpperCase().contains(query.toUpperCase())
                    || v.getGtin().toString().contains(query.toString().trim())
                    || v.getCodigoInterno().contains(query.toString().trim())) {
                r.add(v.getGtin() + " - " + v.getDescricao());
            }
        }
        return r;
    }

    public List<String> completeFornecedor(String query) {
        setListFornecedores(Fornecedor.retornaFornecedores());
        List<String> r = new ArrayList<String>();
        for (Fornecedor v : getListFornecedores()) {
            if (v.getRazaoSocial().toUpperCase().contains(query.toUpperCase())
                    || v.getNomeFantasia().toUpperCase().contains(query.toUpperCase())
                    || v.getId().toString().toUpperCase().contains(query.toUpperCase())) {
                r.add(v.getRazaoSocial());
            }
        }
        return r;
    }

    public void handleSelect(SelectEvent event) {
        Boolean achou = false;
        for (Produto p : getListProduto()) {
            String decricao = event.getObject().toString().substring((event.getObject().toString().indexOf("-") + 2), event.getObject().toString().length());
            if (p.getDescricao().toString().toUpperCase().equalsIgnoreCase(decricao.toUpperCase())) {
                setProduto(p);
                achou = true;
                break;
            }
        }
        if (!achou) {
            produto = new Produto();
        }
    }

    public void handleSelectFornecedor(SelectEvent event) {
        Boolean achou = false;
        for (Fornecedor p : getListFornecedores()) {
            if (p.getRazaoSocial().toString().toUpperCase().equalsIgnoreCase(event.getObject().toString().toUpperCase())) {
                nfe_entrada_cabecalho.setIdFornecedor(p);
                achou = true;
                break;
            }
        }
        if (!achou) {
            produto = new Produto();
            setTxt2(new String());
        }
    }

    public void retornProdutoPorCodigo() {
        Produto p = Produto.retornaProdutoPorGtinOuCodInterno(getProduto().getGtin(), getProduto().getGtin());
        if (p != null) {
            setProduto(p);
            setTxt1(p.getDescricao());
        } else {
            produto = new Produto();
            setTxt2(new String());
        }
    }

    public String alterar(Integer idNota) {
        NfeEntradaCabecalho nfe = NfeEntradaCabecalho.retornaNotaPorId(idNota);
        setNfe_entrada_cabecalho(nfe);
        setTxt2(nfe.getIdFornecedor().getRazaoSocial());
        Listnfe_entrada_detalheEdicao = nfe.getListDetalhe();
        return "NF_Entrada.jsf";
    }

    public void excluirNota() {
        try {
            NfeEntradaCabecalho nfe = NfeEntradaCabecalho.retornaNotaPorId(nfe_entrada_cabecalho.getId());
            atualizaEstoque(nfe.getListDetalhe(), "S");
            nfe.setExcluida('S');
            nfe = nfe.salvar();
            JSFUtil.addMessageSucesso("Nota excluida com sucesso.");
            JSFUtil.addMessageSucesso("Estoque atualizado.");
            InicializaObj();
        } catch (Exception e) {
            JSFUtil.addMessageErro("Erro ao excluir nota " + e);
        }
    }

    public void retornaFornecedorPorId() {
        Fornecedor f = Fornecedor.retornaFornecedorPorId(getNfe_entrada_cabecalho().getIdFornecedor().getId());
        if (f != null) {
            nfe_entrada_cabecalho.setIdFornecedor(f);
            setTxt2(f.getRazaoSocial());
        } else {
            nfe_entrada_cabecalho.setIdFornecedor(new Fornecedor());
            setTxt2(new String());
        }
    }

    public void adicionaItem() {
        if (nfe_entrada_detalhe.getQuantidade().intValue() <= 0) {
            JSFUtil.addMessageErro("A quantidade deve ser maior que 0");
        } else if (produto.getGtin().toString().equalsIgnoreCase("")) {
            JSFUtil.addMessageErro("Informe um produto!!");
        } else {
            NfeEntradaDetalhe det = new NfeEntradaDetalhe();
            det.setIdNfeEntradaCabecalho(nfe_entrada_cabecalho);
            det.setQuantidade(nfe_entrada_detalhe.getQuantidade());
            det.setValorUnitario(produto.getValorVenda());
            det.setValorTotal(produto.getValorVenda().multiply(det.getQuantidade()));
            det.setIdProduto(produto);
            det.setIdUnidadeProduto(nfe_entrada_detalhe.getIdUnidadeProduto());
            det.setValorIcms(new BigDecimal(10));
            det.setValorIpi(new BigDecimal(10));
            nfe_entrada_cabecalho.getListDetalhe().add(det);

            //atrualizando o tatol dos produtos
            BigDecimal novoValor = nfe_entrada_cabecalho.getValorTotalProdutos().add(det.getQuantidade().multiply(produto.getValorVenda()));
            nfe_entrada_cabecalho.setValorTotalProdutos(novoValor);
            nfe_entrada_cabecalho.setValorTotalNfe(novoValor);


            //inicializando objetosd
            nfe_entrada_detalhe = new NfeEntradaDetalhe();
            produto = new Produto();
            txt1 = new String();
        }
    }

    public void removeItem(Integer idProduto) {
        try {
            for (NfeEntradaDetalhe l : nfe_entrada_cabecalho.getListDetalhe()) {
                if (idProduto.intValue() == idProduto) {
                    nfe_entrada_cabecalho.getListDetalhe().remove(l);
                }
            }
        } catch (Exception e) {
            JSFUtil.addMessageErro("Erro ao excluir item: " + e);
        }
    }

    public void salvar() {
        try {
            if (nfe_entrada_cabecalho.getListDetalhe().isEmpty()) {
                JSFUtil.addMessageErro("Nenhum Item foi adicionado na nota!!");
            } else if (nfe_entrada_cabecalho.getIdFornecedor().getId().toString().equals("0") || nfe_entrada_cabecalho.getIdFornecedor().getId().toString().equals("")) {
                JSFUtil.addMessageErro("Informe o fornecedor!!");
            } else {
                nfe_entrada_cabecalho.setData_entrada(new Date());
                nfe_entrada_cabecalho.setExcluida('N');
                nfe_entrada_cabecalho = nfe_entrada_cabecalho.salvar();
                //TODO : Atualiza estoque ao salvar nota
                //TODO : Atualizar Hash tripa do produto
                atualizaEstoque(nfe_entrada_cabecalho.getListDetalhe(), "A");

                //inicializando os objetos
                InicializaObj();
                JSFUtil.addMessageSucesso("Nota salva com sucesso!!");
            }
        } catch (Exception e) {
            JSFUtil.addMessageErro("Erro ao salvar Nota" + e);
        }
    }

    public void InicializaObj() {
        nfe_entrada_cabecalho = new NfeEntradaCabecalho();
        nfe_entrada_detalhe = new NfeEntradaDetalhe();
        produto = new Produto();
        txt1 = new String();
        txt2 = new String();
        Listnfe_entrada_detalheEdicao = new ArrayList<NfeEntradaDetalhe>();
    }

    private void atualizaEstoque(List<NfeEntradaDetalhe> listItens, String TpMovimento) throws NoSuchAlgorithmException, UnsupportedEncodingException {
        //TpMovimento = A: Acrescimo no estoque, S: subtrai estoque
        SimpleDateFormat formatoData = new SimpleDateFormat("dd/MM/yyyy");
        for (NfeEntradaDetalhe list : listItens) {
            BigDecimal estoqueAtual, novoSaldoEstoque;
            Produto prod = JPAUtil.buscarPorId(Produto.class, list.getIdProduto().getId());//realizando pesquisa pra retornar o valor que esta no banco neste momento
            estoqueAtual = prod.getQtdEstoque();
            if (TpMovimento.equalsIgnoreCase("A")) {//acrescimo
                novoSaldoEstoque = estoqueAtual.add(list.getQuantidade());//alterando o estoque 
            } else {//subtrai estoque
                novoSaldoEstoque = estoqueAtual.subtract(list.getQuantidade());//alterando o estoque 
            }
            String tripa = prod.getGtin()
                    + prod.getDescricao()
                    + prod.getDescricaoPdv()
                    + Biblioteca.formatoDecimal("Q", Double.parseDouble(novoSaldoEstoque.toString()))
                    + formatoData.format(prod.getDataEstoque())
                    + prod.getCst()
                    + Biblioteca.formatoDecimal("V", Double.parseDouble(prod.getTaxaIcms().toString()))
                    + Biblioteca.formatoDecimal("V", Double.parseDouble(prod.getValorVenda().toString()))
                    + "0";
            prod.setQtdEstoque(novoSaldoEstoque);
            prod.setHashTripa(Biblioteca.MD5String(tripa));
            prod.setHashIncremento(-1);
            prod = prod.salvar();
        }
    }

    /**
     * @return the listProduto
     */
    public List<Produto> getListProduto() {
        return listProduto;
    }

    /**
     * @param listProduto the listProduto to set
     */
    public void setListProduto(List<Produto> listProduto) {
        this.listProduto = listProduto;
    }

    /**
     * @return the produto
     */
    public Produto getProduto() {
        return produto;
    }

    /**
     * @param produto the produto to set
     */
    public void setProduto(Produto produto) {
        this.produto = produto;
    }

    /**
     * @return the nfe_entrada_detalhe
     */
    public NfeEntradaDetalhe getNfe_entrada_detalhe() {
        return nfe_entrada_detalhe;
    }

    /**
     * @param nfe_entrada_detalhe the nfe_entrada_detalhe to set
     */
    public void setNfe_entrada_detalhe(NfeEntradaDetalhe nfe_entrada_detalhe) {
        this.nfe_entrada_detalhe = nfe_entrada_detalhe;
    }

    /**
     * @return the listFornecedores
     */
    public List<Fornecedor> getListFornecedores() {
        return listFornecedores;
    }

    /**
     * @param listFornecedores the listFornecedores to set
     */
    public void setListFornecedores(List<Fornecedor> listFornecedores) {
        this.listFornecedores = listFornecedores;
    }

    /**
     * @return the txt2
     */
    public String getTxt2() {
        return txt2;
    }

    /**
     * @param txt2 the txt2 to set
     */
    public void setTxt2(String txt2) {
        this.txt2 = txt2;
    }
}
